﻿using System;
using System.Collections.Generic;
using System.Drawing;
using RaytracerLib.Layers;
using RaytracerLib.MathLib;
using TomanuExtensions;
using RaytracerLib.Layers.OverlayCorrectors;
using System.Linq;
using RaytracerLib.Postprocessing;
using RaytracerLib.Samplers;
using System.Diagnostics;
using YAXLib;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace RaytracerLib.Resamplers
{
    public class NetResizerResampler : Resampler
    {
        private ColorArrayFloat m_rays;
        private int m_scale;
        private InterpolationMode m_interpolation_mode = InterpolationMode.Bicubic;
        private double m_filter_ray;

        [YAXNode]
        public InterpolationMode InterpolationMode
        {
            get
            {
                return m_interpolation_mode;
            }
            set
            {
                m_interpolation_mode = value;

                switch (InterpolationMode)
                {
                    case InterpolationMode.Bicubic: m_filter_ray = 2; break;
                    case InterpolationMode.Bilinear: m_filter_ray = 1; break;
                    case InterpolationMode.High: m_filter_ray = 3; break;
                    case InterpolationMode.HighQualityBicubic: m_filter_ray = 2; break;
                    case InterpolationMode.HighQualityBilinear: m_filter_ray = 1; break;
                    case InterpolationMode.Low: m_filter_ray = 0.5; break;
                    case InterpolationMode.NearestNeighbor: m_filter_ray = 0.5; break;
                    default: throw new NotImplementedException();
                }
            }
        }

        internal override void SetRayColor(Vector2 a_pixel, ColorFloat a_color)
        {
            a_pixel *= m_scale;
            m_rays.SetColor((int)a_pixel.X, (int)a_pixel.Y, a_color);
        }

        internal override void Resample(Rectangle a_rect, ColorArrayFloat a_dest)
        {
            using (Bitmap src_bmp = m_rays.GetBitmap())
            {
                using (Bitmap dest_bmp = new Bitmap(Film.Width, Film.Height))
                {
                    using (Graphics g = Graphics.FromImage(dest_bmp))
                    {
                        g.InterpolationMode = InterpolationMode;
                        g.DrawImage(src_bmp, new Rectangle(0, 0, dest_bmp.Width, dest_bmp.Height),
                            new Rectangle(0, 0, src_bmp.Width, src_bmp.Height), GraphicsUnit.Pixel);
                    }

                    using (Bitmap rect_bmp = new Bitmap(a_rect.Width, a_rect.Height))
                    {
                        using (Graphics g = Graphics.FromImage(rect_bmp))
                            g.DrawImage(dest_bmp, 0, 0, a_rect, GraphicsUnit.Pixel);

                        ColorArrayFloat rect_area = new ColorArrayFloat(rect_bmp);
                        a_dest.Draw(rect_area, new Rectangle(0, 0, rect_area.Width, rect_area.Height),
                            a_rect);
                    }
                }
            }
        }

        internal override void RenderStart(RenderStartPhase a_phase)
        {
            if (a_phase == RenderStartPhase.PrepareObjectToRender)
            {
                UniformSampler sampler = Film.Sampler as UniformSampler;

                if (sampler == null)
                    throw new InvalidOperationException();

                m_scale = sampler.Subresolution;

                m_rays = new ColorArrayFloat(
                    Film.Width * m_scale,
                    Film.Height * m_scale);
            }
        }

        public override ResamplerType ResamplerType
        {
            get
            {
                return ResamplerType.NetResizer;
            }
        }

        internal override double FilterRay
        {
            get 
            {
                return m_filter_ray;
            }
        }
    }
}